package bll

import (
	"context"
	"encoding/json"
	log "manager/collector/logger"
	"manager/utils"

	"manager/event"
	"manager/model"
	"manager/model/entity"
	"manager/store"
	"manager/store/postgres"
	"time"

	"manager/auth"
)

type cyclingRecode struct {
	iCyclingRecode store.ICyclingRecode
}

var CyclingRecode = &cyclingRecode{
	iCyclingRecode: postgres.CyclingRecode,
}

func (a *cyclingRecode) init() func() {
	return func() {}
}

func (a *cyclingRecode) onEvent(data *event.Data) {
	if data == nil || (data.Type != event.Event_Bind_Bike && data.Type != event.Event_UnBind_Bike) {
		return
	}
	_data, _ := json.Marshal(data)
	log.Info("---------------- cyclingRecode onEvent data:", string(_data))

	// 绑定车辆
	if event.Event_Bind_Bike == data.Type {
		// 解析参数
		obj := data.Data.(*event.BindBike)
		if obj == nil {
			log.Error("cyclingRecode onEvent err")
			return
		}

		// 参数校验
		if obj.BikeId == 0 || obj.UserId == 0 {
			log.Errorf("cyclingRecode onEvent params error userId:%v bikeId:%v", obj.UserId, obj.BikeId)
			return
		}

		// 创建记录
		_, err := postgres.CyclingRecode.Create(context.Background(), &entity.CyclingRecode{
			UserId:        obj.UserId,
			EbikeId:       obj.BikeId,
			AccompanyDays: 1,
		})
		if err != nil {
			log.Error("cyclingRecode Create onEvent err:", err)
		}
		return
	}

	// 解绑车辆
	if event.Event_UnBind_Bike == data.Type {
		// 解析参数
		obj := data.Data.(*event.UnBindBike)
		if obj == nil {
			log.Error("cyclingRecode Event_UnBind_Bike onEvent err")
			return
		}

		// 参数校验
		if obj.BikeId == 0 || obj.UserId == 0 {
			log.Errorf("cyclingRecode onEvent Event_UnBind_Bike params error userId:%v bikeId:%v", obj.UserId, obj.BikeId)
			return
		}

		// 查询信息
		info, _ := postgres.CyclingRecode.Find(context.Background(), &model.CyclingRecodeInfoRequest{
			UserId:  &obj.UserId,
			EbikeId: &obj.BikeId,
		})
		if info.Id == 0 {
			log.Errorf("cyclingRecode onEvent Event_UnBind_Bike record not exist error userId:%v bikeId:%v", obj.UserId, obj.BikeId)
			return
		}

		// 创建记录
		err := a.Delete(context.Background(), &model.CyclingRecodeDeleteRequest{
			Id: info.Id,
		})
		if err != nil {
			log.Error("cyclingRecode Delete onEvent err:", err)
		}
		return
	}
}

// Create 创建
func (a *cyclingRecode) Create(ctx context.Context, in *model.CyclingRecodeCreateRequest) error {
	var (
		err error
	)

	// 获取用户Id
	in.UserId, _ = auth.ContextUserID(ctx)

	// 构建创建现场数据
	c := buildCyclingRecode(in)
	_, err = a.iCyclingRecode.Create(ctx, c)
	return err
}

// UpdateCyclingRecord 更新
func (a *cyclingRecode) UpdateCyclingRecord(userId, bikeId int64, mileage, maxRideMileage int) error {
	// 查询信息
	info, _ := postgres.CyclingRecode.Find(context.Background(), &model.CyclingRecodeInfoRequest{
		UserId:  &userId,
		EbikeId: &bikeId,
	})
	if info.Id == 0 {
		// 创建记录
		id, _ := postgres.CyclingRecode.Create(context.Background(), &entity.CyclingRecode{
			UserId:        userId,
			EbikeId:       bikeId,
			AccompanyDays: 1,
		})
		if id == 0 {
			return nil
		}

		// 查询信息
		info, _ = postgres.CyclingRecode.Find(context.Background(), &model.CyclingRecodeInfoRequest{
			UserId:  &userId,
			EbikeId: &bikeId,
		})
		if info.Id == 0 {
			return nil
		}
	}

	if info.MaxRideMileage > maxRideMileage {
		maxRideMileage = info.MaxRideMileage
	}

	// 陪伴天数
	accompanyDays := utils.SpanDayNumber(info.CreatedAt, time.Now().Unix())

	// 更新
	return a.Update(context.Background(), &model.CyclingRecodeUpdateRequest{
		Id:             info.Id,
		TotalMileage:   &mileage,
		MaxRideMileage: &maxRideMileage,
		AccompanyDays:  &accompanyDays,
	})
}

// Update 更新
func (a *cyclingRecode) Update(ctx context.Context, in *model.CyclingRecodeUpdateRequest) error {
	var (
		dict = make(map[string]interface{})
	)

	updateAt := time.Now().Unix()
	in.UpdatedAt = &updateAt

	if in.UserId != nil {
		dict["user_id"] = in.UserId
	}

	if in.EbikeId != nil {
		dict["ebike_id"] = in.EbikeId
	}

	if in.TotalMileage != nil {
		dict["total_mileage"] = in.TotalMileage
	}

	if in.MaxRideMileage != nil {
		dict["max_ride_mileage"] = in.MaxRideMileage
	}

	if in.AccompanyDays != nil {
		dict["accompany_days"] = in.AccompanyDays
	}

	if in.UpdatedAt != nil {
		dict["updated_at"] = in.UpdatedAt
	}

	// do other update here
	return a.iCyclingRecode.Update(ctx, in.Id, dict)
}

// Delete 删除
func (a *cyclingRecode) Delete(ctx context.Context, in *model.CyclingRecodeDeleteRequest) error {
	return a.iCyclingRecode.Delete(ctx, in.Id)
}

// List 列表查询
func (a *cyclingRecode) List(ctx context.Context, in *model.CyclingRecodeListRequest) (*model.CyclingRecodeListResponse, error) {
	var (
		err   error
		total int
		list  []*entity.CyclingRecode
		out   = &model.CyclingRecodeListResponse{}
	)

	userId, _ := auth.ContextUserID(ctx)
	in.UserId = &userId
	if total, list, err = a.iCyclingRecode.List(ctx, in); err != nil {
		return nil, err
	}

	out.Total = total
	out.List = model.CyclingRecodesEntityToDto(list)

	return out, nil
}

// Find 列表查询
func (a *cyclingRecode) Find(ctx context.Context, in *model.CyclingRecodeInfoRequest) (*model.CyclingRecodeInfo, error) {
	var (
		err  error
		data *entity.CyclingRecode
		out  = &model.CyclingRecodeInfo{}
	)

	userId, _ := auth.ContextUserID(ctx)
	in.UserId = &userId

	// 查询信息
	if data, err = a.iCyclingRecode.Find(ctx, in); err != nil {
		return nil, err
	}

	// 陪伴天数
	data.AccompanyDays = utils.SpanDayNumber(data.CreatedAt, time.Now().Unix()) + 1

	out = model.CyclingRecodeEntityToDto(data)
	return out, nil
}

// buildCyclingRecode 构建创建数据现场
func buildCyclingRecode(in *model.CyclingRecodeCreateRequest) *entity.CyclingRecode {
	// todo: check the entity is required
	return &entity.CyclingRecode{

		UserId: in.UserId,

		EbikeId: in.EbikeId,

		TotalMileage: in.TotalMileage,

		MaxRideMileage: in.MaxRideMileage,

		AccompanyDays: in.AccompanyDays,

		CreatedAt: time.Now().Unix(),

		UpdatedAt: time.Now().Unix(),
	}
}
